package cn.edu.sdjzu.xg.eagle.controller;

import cn.edu.sdjzu.xg.eagle.entity.User;
import cn.edu.sdjzu.xg.eagle.exception.BysjException;
import cn.edu.sdjzu.xg.eagle.factory.ServiceFactory;
import cn.edu.sdjzu.xg.eagle.service.UserServiceImpl;
import cn.edu.sdjzu.xg.eagle.service.UserServiceInterface;
import cn.edu.sdjzu.xg.eagle.util.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.naming.AuthenticationException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Date;

@WebServlet("/loginController")
public class LoginController extends HttpServlet {

    private static final Logger logger = LoggerFactory.getLogger(LoginController.class);
    private static final String SECRET_KEY = "XG23";
    private static final long TOKEN_EXPIRATION_TIME = 30 * 60 * 1000;

    private final UserServiceInterface userService = ServiceFactory.getService(
            UserServiceInterface.class, "UserServiceImpl"
    );

    private final JwtTokenGenerator jwtTokenGenerator = new JwtTokenGenerator(SECRET_KEY, TOKEN_EXPIRATION_TIME);
    private final ResponseHandler responseHandler = new ResponseHandler();

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=UTF-8");
        try {
            User userToLogin = parseUserFromRequest(req);
            validateUserCredentials(userToLogin);
            String token = jwtTokenGenerator.generateToken(userToLogin.getId());
            responseHandler.sendSuccessResponse(resp, token);
        } catch (IllegalArgumentException e) {
            logger.warn("无效请求参数：{}", e.getMessage());
            responseHandler.sendErrorResponse(resp, e.getMessage(), 400);
        } catch (AuthenticationException e) {
            logger.warn("认证失败：{}", e.getMessage());
            responseHandler.sendErrorResponse(resp, e.getMessage(), 401);
        } catch (SQLException e) {
            logger.error("数据库操作异常", e);
            responseHandler.sendErrorResponse(resp, "数据库操作异常", 500);
        } catch (Exception e) {
            logger.error("系统异常", e);
            responseHandler.sendErrorResponse(resp, "系统异常", 500);
        }
    }

    private User parseUserFromRequest(HttpServletRequest request) throws IOException {
        String userJson = JSONUtil.getJSON(request);
        User user = JSON.parseObject(userJson, User.class);

        if (user == null || user.getUsername() == null || user.getPassword() == null) {
            throw new IllegalArgumentException("请求参数不完整");
        }
        return user;
    }

    private void validateUserCredentials(User user) throws SQLException, AuthenticationException {
        userService.login(user);
        if (user.getId() == null) {
            throw new BysjException("用户不存在/密码错误");
        }
    }

    private static class JwtTokenGenerator {
        private final String secretKey;
        private final long expirationTime;

        public JwtTokenGenerator(String secretKey, long expirationTime) {
            this.secretKey = secretKey;
            this.expirationTime = expirationTime;
        }

        public String generateToken(Long userId) {
            return JWT.create()
                    .withSubject(String.valueOf(userId))
                    .withExpiresAt(new Date(System.currentTimeMillis() + expirationTime))
                    .sign(Algorithm.HMAC256(secretKey));
        }
    }

    private class ResponseHandler {
        public void sendSuccessResponse(HttpServletResponse response, String token) throws IOException {
            JSONObject responseBody = new JSONObject();
            responseBody.put("message", "登录成功");
            responseBody.put("code", "200");
            responseBody.put("token", token);
            sendResponse(response, responseBody);
        }

        public void sendErrorResponse(HttpServletResponse response, String errorMsg, int statusCode) throws IOException {
            JSONObject responseBody = new JSONObject();
            responseBody.put("message", errorMsg);
            responseBody.put("code", statusCode);
            response.setStatus(statusCode);
            sendResponse(response, responseBody);
        }

        private void sendResponse(HttpServletResponse response, JSONObject responseBody) throws IOException {
            response.getWriter().println(JSON.toJSONString(responseBody));
        }
    }
}